// Copyright (c) 2022 Presto Labs Pte. Ltd.
// Author: junglekim
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/join.hpp>
#include <fmt/core.h>
#include <gflags/gflags.h>

#include "cc/appcoin2/support/mm_helper/mm_educator_strategy.h"
#include "coin2/app/driver.h"

DEFINE_double(max_loss_quote, 0.0, "Max loss amount in quote(maybe USD?)");
DEFINE_double(lot_size, 0.0, "Lot size for aggression");
DEFINE_double(order_update_period, 1.0, "order_update_period sec");

DEFINE_string(start_datetime, "", "datetime lower bound");
DEFINE_double(buy_price, 0, "buy price");
DEFINE_double(sell_price, 0, "buy price");

DEFINE_string(mea, "", "mea and recipe e.g. Spot.Binance.v1.snapshot");
DEFINE_string(symbol, "", "symbol to trade");
DEFINE_string(key_path, "", "path to keyfile");
DEFINE_string(driver, "", "default driver path");

void setLiveConfig(coin2::app::DriverConfig* driverConfig) {
  auto* mutable_feed = driverConfig->mutable_feed();

  mutable_feed->mutable_common()->set_type(
      ::coin2::exchange::feed::FeedSystemType::FEED_SYSTEM_TYPE_LIVE);
  coin2::exchange::feed::FeedSystemConfig feedSytemConfig;
  std::vector<std::string> mea_list;
  boost::split(mea_list, FLAGS_mea, boost::is_any_of("."));
  CHECK_EQ(mea_list.size(), 4) << "mea should be Spot.Binance.v1.snapshot";
  auto recipe = mea_list.back();
  mea_list.pop_back();
  auto mea = boost::algorithm::join(mea_list, ".");

  feedSytemConfig.set_recipe(recipe);
  feedSytemConfig.set_mea(mea);
  feedSytemConfig.mutable_products()->add_norms(FLAGS_symbol);
  feedSytemConfig.mutable_websocket()->set_num_workers(1);
  if (mea == "Spot.Gopax.v1") {
    feedSytemConfig.mutable_websocket()->add_key_filepaths(FLAGS_key_path);
  }
  driverConfig->mutable_feed()->mutable_exchanges()->insert({FLAGS_mea, feedSytemConfig});

  coin2::exchange::order::OrderSystemConfig orderSystemConfig;
  orderSystemConfig.set_mea(mea);
  orderSystemConfig.set_type(coin2::exchange::order::OrderSystemType::ORDER_SYSTEM_TYPE_LIVE_OG);
  orderSystemConfig.mutable_products()->add_norms(FLAGS_symbol);
  orderSystemConfig.mutable_connection_config()->set_key_filepath(FLAGS_key_path);
  driverConfig->mutable_order()->mutable_exchanges()->insert({FLAGS_mea, orderSystemConfig});

  std::cout << driverConfig->DebugString();
  std::cout << driverConfig->order().exchanges().cbegin()->second.mea();
  std::cout << driverConfig->order().exchanges().cbegin()->second.products().norms()[0];
}

int main(int argc, char* argv[]) {
  google::InitGoogleLogging(argv[0]);
  gflags::ParseCommandLineFlags(&argc, &argv, true);
  coin2::app::DriverConfig app_config;
  if (FLAGS_driver == "") {
    setLiveConfig(&app_config);
  } else {
    auto path = std::experimental::filesystem::path(FLAGS_driver);
    app_config.MergeFrom(coin2::base::config::DriverConfigFromJson(path));
  }
  coin2::appcoin2::support::mm_helper::MMEducatorStrategy strategy(
      FLAGS_max_loss_quote,
      FLAGS_lot_size,
      FLAGS_order_update_period,
      FLAGS_start_datetime,
      FLAGS_buy_price,
      FLAGS_sell_price);

  coin2::app::Driver driver(app_config, &strategy);
  driver.RegisterCleanupHandler();
  driver.Run();
  return 0;
}
